#include "hashTable.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

struct hashTableEntry* hashTable[MOD];

struct hashTableEntry* createEntry(int key, char* value) {	
	struct hashTableEntry* result = malloc(sizeof(struct hashTableEntry));

	int valueLength = strlen(value);

	if (value[valueLength - 1] == '\n') {
		value[valueLength - 1] = 0;
		valueLength--;
	}

	char* valueCopy = malloc(valueLength * sizeof(char));
	strcpy(valueCopy, value);

	result -> key = key;
	result -> value = valueCopy;
	result -> next = NULL;
	
	return result;
}

int calcHash(char* str) {
	static bool firstCall = true;
	static long long powers[MAX_LINE_LENGTH];

	if (firstCall) { firstCall = false; powers[0] = 1; for (int i = 1; i <
	MAX_LINE_LENGTH; i++) { powers[i] = (powers[i - 1] * P) % MOD; } }

	long long result = 0;

	for (int i = 0; str[i] != 0 && str[i] != '\n'; i++) {
		result += (long long) ((str[i] - 32 + 1)) * powers[i] % MOD;
		result %= MOD; 
	}

	return result;
}

bool find(char* str) {
	int chainLength = 0;
	int hash = calcHash(str);

	struct hashTableEntry* currentEntry = hashTable[hash];

	while (currentEntry != NULL) {
		chainLength++;
		if (strcmp(str, currentEntry -> value) == 0) {			
			return true;
		}

		currentEntry = currentEntry -> next;
	}
	
	return false;
}

bool add(char* str) {
	int chainLength = 0;
	int hash = calcHash(str);

	struct hashTableEntry* currentEntry = hashTable[hash];

	if (currentEntry == NULL) {
		hashTable[hash] = createEntry(hash, str);		
		return true;
	}	

	struct hashTableEntry* prevEntry;

	while (currentEntry != NULL) {		
		chainLength++;		
		if (strcmp(str, currentEntry -> value) == 0) {			
			return false;
		}				

		prevEntry = currentEntry;
		currentEntry = currentEntry -> next;		
	} 
	
	struct hashTableEntry* newEntry = createEntry(hash, str);
	prevEntry -> next = newEntry;

	return true;
}